package com.terrytian.springboottq.aop;

import com.alibaba.fastjson.JSON;
import com.terrytian.springboottq.annotation.Prevent;
import com.terrytian.springboottq.common.BusinessCode;
import com.terrytian.springboottq.common.BusinessException;
import com.terrytian.springboottq.convert.PreventConvert;
import com.terrytian.springboottq.handler.PreventHandler;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;

/**
 * 防刷切面实现类
 *
 * @author: tianqing
 * @date: 2022/11/26 20:27
 */
@Aspect
@Component
@Slf4j
public class PreventAop {

    /**
     * 切入点
     */
    @Pointcut("@annotation(com.terrytian.springboottq.annotation.Prevent)")
    public void pointcut() {
    }


    /**
     * 处理前
     *
     * @return
     */
    @Before("pointcut()")
    public void joinPoint(JoinPoint joinPoint) throws Exception {
        Object[] args = joinPoint.getArgs();

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();

        Prevent preventAnnotation = method.getAnnotation(Prevent.class);
        String methodFullName = method.getDeclaringClass().getName() + method.getName();

        //空入参方法处理逻辑
        Class<? extends PreventConvert> convertNullAble = preventAnnotation.nullAble();
        if (convertNullAble.equals(PreventConvert.class)){
            String requestStr = JSON.toJSONString(joinPoint.getArgs()[0]);
            if (!StringUtils.hasText(requestStr) || requestStr.equalsIgnoreCase("{}")) {
                throw new BusinessException("[防刷]入参不允许为空");
            }
        }else {
            //如果是A.isAssignableFrom(B) 确定一个类(B)是不是继承来自于另一个父类(A)，一个接口(A)是不是实现了另外一个接口(B)，或者两个类相同。
            if (PreventConvert.class.isAssignableFrom(convertNullAble)){
                //允许用在空方法上，需要自定义
                PreventConvert convert = convertNullAble.newInstance();
                try {
                    convert.convert(args);
                }catch (Throwable t){
                    log.error("[PreventAop]some errors happens in PreventAop's nullAble",t);
                }
            }
        }

        StringBuilder sb = new StringBuilder();

        Class<? extends PreventConvert> convertClazz = preventAnnotation.convert();
        //处理自定义convert
        boolean isPreventConvert;
        if (convertClazz.equals(PreventConvert.class)){
            throw new BusinessException(BusinessCode.EXCEPTION,"无效的转换");
        }else {
            //如果是A.isAssignableFrom(B) 确定一个类(B)是不是继承来自于另一个父类(A)，一个接口(A)是不是实现了另外一个接口(B)，或者两个类相同。
            isPreventConvert = PreventConvert.class.isAssignableFrom(convertClazz);
        }
        if (isPreventConvert){
            PreventConvert convert = convertClazz.newInstance();
            try {
                sb.append(convert.convert(args));
            }catch (Throwable t){
                log.error("[PreventAop]some errors happens in PreventAop's convert",t);
            }
        }

        //自定义策略
        Class<? extends PreventHandler> strategy = preventAnnotation.strategy();
        boolean isPreventHandler;
        if (strategy.equals(PreventHandler.class)){
            throw new BusinessException(BusinessCode.EXCEPTION,"无效的处理策略");
        }else {
            isPreventHandler = PreventHandler.class.isAssignableFrom(strategy);
        }
        if (isPreventHandler){
            PreventHandler handler = strategy.newInstance();
            try {
                handler.handle(sb.toString(),preventAnnotation,methodFullName);
            }catch (BusinessException be){
                throw be;
            }catch (Throwable t){
                log.error("[PreventAop]some errors happens in PreventAop's strategy",t);
            }
        }
        return;
    }
}
